package com.knowledge.plus.aop.annotation;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;


/**
 * 切面注解 Aspect 使用入门
 * 1、@Aspect：声明本类为切面类
 * 2、@Component：将本类交由 Spring 容器管理
 * 3、@Order：（可不写）指定切入执行顺序，数值越小，切面执行顺序越靠前，默认为 Integer.MAX_VALUE
 *
 * @author PF.Tian
 * @since 2021/09/13
 */
@Aspect
@Component
public class MethodAnnotationAspect {

    /**
     * 注解 @MethodAnnotation
     */
    @Pointcut("@annotation(MethodAnnotation)")
    private void controllerAspect() {
    }

    /**
     * 方法执行前的预处理
     */
    @Before("controllerAspect()")
    public void Before(JoinPoint joinPoint) {
        String classname = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        List<Object> args = Arrays.asList(joinPoint.getArgs());
        System.out.println("@before：class name: " + classname + ", method name: " + methodName + " " + args + "\n");
    }

    /**
     * 方法执行的环绕控制
     */
    @Around("controllerAspect()")
    public Object Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("@Around：执行目标方法之前...");
        Object obj = proceedingJoinPoint.proceed();
        System.out.println("@Around：执行目标方法之后...");
        System.out.println("@Around：被织入的目标对象为：" + proceedingJoinPoint.getTarget());
        System.out.println("@Around：原返回值：" + obj + "，这是返回结果的后缀\n");
        return obj;
    }

    /**
     * 异常处理
     */
    @AfterThrowing("controllerAspect()")
    public void AfterThrowing() {
        System.out.println("异常通知....\n");
    }

    /**
     * 方法执行后的清理
     */
    @After("controllerAspect()")
    public void After(JoinPoint point) {
        System.out.println("@After：模拟释放资源...");
        System.out.println("@After：目标方法为：" +
                point.getSignature().getDeclaringTypeName() +
                "." + point.getSignature().getName());
        System.out.println("@After：参数为：" + Arrays.toString(point.getArgs()));
        System.out.println("@After：被织入的目标对象为：" + point.getTarget() + "\n");
    }

    /**
     * 返回值处理
     */
    @AfterReturning("controllerAspect()")
    public void AfterReturning(JoinPoint point) {
        System.out.println("@AfterReturning：模拟日志记录功能...");
        System.out.println("@AfterReturning：目标方法为：" +
                point.getSignature().getDeclaringTypeName() +
                "." + point.getSignature().getName());
        System.out.println("@AfterReturning：参数为：" +
                Arrays.toString(point.getArgs()));
        System.out.println("@AfterReturning：返回值为：");
        System.out.println("@AfterReturning：被织入的目标对象为：" + point.getTarget() + "\n");
    }

}
